#include "certtablemodel.h"

#ifndef ENABLE_GMSSL
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#endif

#include "openssl/opensslhelper.h"



CertTableModel::CertTableModel(QObject *parent,
                               Delegate* delegate)
  : QAbstractTableModel{parent},
    delegate_(delegate)
{
  if(delegate_)
    delegate_->SetModel(this);
}

CertTableModel::~CertTableModel()
{
  if(delegate_)
    delegate_ = nullptr;
}

void CertTableModel::SetSortType(SortType sort_type) {
  delegate_->SetSortType(sort_type);
  beginResetModel();
  certs_.clear();
  endResetModel();
}

void CertTableModel::SetCategory(const QString &category)
{
  QList<X509* > certs = delegate_->GetCertificates(category);
  beginInsertRows(QModelIndex(), 0, certs.size() -1);
  certs_.swap(certs);
  endInsertRows();
}

int CertTableModel::columnCount(const QModelIndex &parent) const
{
  return (int)X509Field::TotalCount;
}

int CertTableModel::rowCount(const QModelIndex &parent) const
{
  return certs_.size();
}

QVariant CertTableModel::data(const QModelIndex &index, int role) const
{
  X509* cert = certs_[index.row()];
  if(role != Qt::DisplayRole && role != Qt::ToolTipRole)
    return QVariant();

  static constexpr int X509_FIELD_LEN = 200;

  static char val[X509_FIELD_LEN+1];
  memset(val, 0, X509_FIELD_LEN+1);

#ifndef ENABLE_GMSSL
  switch((X509Field)index.column()) {
    case X509Field::Subject:
      X509_NAME_oneline(X509_get_subject_name(cert), val, X509_FIELD_LEN);
      return QString::fromUtf8(val);

    case X509Field::Issuer:
      X509_NAME_oneline(X509_get_issuer_name(cert), val, X509_FIELD_LEN);
      return QString::fromUtf8(val);
    case X509Field::FriendlyName:
      return QVariant();
    case X509Field::KeyUsage: {
      ASN1_BIT_STRING* usage = (ASN1_BIT_STRING*)X509_get_ext_d2i(
            cert, NID_key_usage, NULL, NULL);
      QStringList key_usage;
      for(int i = 0; i < delegate_->GetKeyUsageName().size(); i++) {
        if(ASN1_BIT_STRING_get_bit(usage, i))
          key_usage.append(delegate_->GetKeyUsageName()[i]);
      }

      key_usage += delegate_->GetExtendedKeyUsage(cert);

      return key_usage.join(',');
    }

  case X509Field::ValidityFrom: {
      ASN1_TIME* from = X509_get_notBefore(cert);
      QString from_val = OpensslHelper::ASN1TIME2QString(from);
      return from_val;
  }
  case X509Field::ValidityTo:{
    ASN1_TIME* to = X509_get_notBefore(cert);
    QString to_val = OpensslHelper::ASN1TIME2QString(to);
    return to_val;
  }
    default:
      break;
  }
#endif

  return QVariant();
}

QVariant CertTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
  if(orientation != Qt::Horizontal)
    return QVariant();

  if(role != Qt::DisplayRole && role != Qt::ToolTipRole)
    return QVariant();

  switch((X509Field)section) {
    case X509Field::Subject:
      return tr("certificate subject");
    case X509Field::Issuer:
      return tr("certificate issuer");
    case X509Field::FriendlyName:
      return tr("friendly name");
    case X509Field::KeyUsage:
      return tr("key usage");
    case X509Field::ValidityFrom:
      return tr("validity start time");
    case X509Field::ValidityTo:
      return tr("validity end time");
    default:
      break;
  }
}
